package com.zensun.system.service.impl;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zensun.common.utils.Assert;
import com.zensun.system.domain.SysDictData;
import com.zensun.system.domain.SysDictType;
import com.zensun.system.domain.dto.SysDictDataDto;
import com.zensun.system.domain.vo.SysDictDataVo;
import com.zensun.system.mapper.SysDictDataMapper;
import com.zensun.system.mapper.SysDictTypeMapper;
import com.zensun.system.service.ISysDictDataService;
import com.zensun.system.util.DictUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

/**
 * 字典 业务层处理
 *
 * @author gmk
 */
@Service
public class SysDictDataServiceImpl extends ServiceImpl<SysDictDataMapper, SysDictData> implements ISysDictDataService {
    @Autowired
    private SysDictDataMapper dictDataMapper;

    @Autowired
    private SysDictTypeMapper dictTypeMapper;

    @Override
    public List<SysDictDataVo> selectDictDataList(SysDictDataDto dictDataDto) {

        Assert.isBlank(dictDataDto.getDictType(), "请填写字典类型");
        // 1.缓存中有直接返回
        List<SysDictDataVo> dictDatas = DictUtils.getDictCache(dictDataDto.getDictType());
        if (CollUtil.isNotEmpty(dictDatas)) {
            return dictDatas;
        }
        // 2.缓存中没有查询数据库
        QueryWrapper<SysDictData> queryWrapper = new QueryWrapper<SysDictData>();
        queryWrapper.eq("dict_type", dictDataDto.getDictType());
        queryWrapper.orderByAsc("dict_sort");
        List<SysDictData> dictDataList = dictDataMapper.selectList(queryWrapper);
        dictDatas = CollStreamUtil.toList(dictDataList, sysDictData -> {
            SysDictDataVo sysDictDataVo = new SysDictDataVo();
            BeanUtils.copyProperties(sysDictData, sysDictDataVo);
            return sysDictDataVo;
        });
        // 3.更新缓存
        if (CollUtil.isNotEmpty(dictDatas)) {
            DictUtils.setDictCache(dictDataDto.getDictType(), dictDatas);
        }
        return dictDatas;
    }

    @Override
    public SysDictDataVo selectDictDataId(Long dictCode) {
        SysDictDataVo sysDictDataVo = new SysDictDataVo();
        SysDictData byId = this.getById(dictCode);
        BeanUtils.copyProperties(byId, sysDictDataVo);
        return sysDictDataVo;
    }

    /**
     * 批量删除字典数据信息
     *
     * @param dictCodes 需要删除的字典数据ID
     * @return 结果
     */
    @Override
    public boolean deleteDictDataByIds(Long[] dictCodes) {
        //查询字典数据对应的字典类型
        List<SysDictData> sysDictDataList = dictDataMapper.selectBatchIds(Arrays.asList(dictCodes));
        boolean row = this.removeByIds(Arrays.asList(dictCodes));
        if (row) {
            for (SysDictData sysDictData : sysDictDataList) {
                //删除缓存中所有的字典类型
                DictUtils.deleteDictCache(sysDictData.getDictType());
            }
        }
        return row;
    }

    /**
     * 新增保存字典数据信息
     *
     * @param dictData 字典数据信息
     * @return 结果
     */
    @Override
    public int insertDictData(SysDictData dictData) {
        // 1.校验
        Assert.isNotTrue(checkDictTpyeExist(dictData), "字典类型未定义，请核实");
        Assert.isNotTrue(checkDictDataUnique(dictData),
                "新增字典数据失败" + " :类型'" + dictData.getDictType() + "'对应的标签'" + dictData.getDictLabel() + "'已存在");
        int row = dictDataMapper.insert(dictData);
        if (row > 0) {
            DictUtils.deleteDictCache(dictData.getDictType());
        }
        return row;
    }

    /**
     * 修改保存字典数据信息
     *
     * @param dictData 字典数据信息
     * @return 结果
     */
    @Override
    public int updateDictData(SysDictData dictData) {
        // 1.校验
        Assert.isNotTrue(checkDictTpyeExist(dictData), "字典类型未定义，请核实");
        Assert.isNotTrue(checkDictDataUnique(dictData),
                "更改字典数据失败" + " :类型 '" + dictData.getDictType() + "'对应的标签 '" + dictData.getDictLabel() + "'已存在");
        int row = dictDataMapper.updateById(dictData);
        if (row > 0) {
            DictUtils.deleteDictCache(dictData.getDictType());
        }
        return row;
    }

    /**
     * 校验字典数据称是否唯一
     *
     * @param dict 字典数据
     * @return 结果
     */
    public boolean checkDictDataUnique(SysDictData dict) {
        boolean result = true;
        //增加或者修改
        Long dictCode = ObjectUtil.isNull(dict.getDictCode()) ? -1L : dict.getDictCode();
        //字典类型和 字典值
        String dictType = dict.getDictType();
        String dictLabel = dict.getDictLabel();
        // 1.根据角色名称查询数据库是否存在此名称
        LambdaQueryWrapper<SysDictData> q = new LambdaQueryWrapper<>();
        q.eq(SysDictData::getDictLabel, dictLabel).eq(SysDictData::getDictType, dictType);
        SysDictData one = this.getOne(q);
        if (ObjectUtil.isNotEmpty(one) && !one.getDictCode().equals(dictCode)) {
            result = false;
        }
        return result;

    }

    /**
     * 校验字典类型是否存在
     *
     * @param dict 字典数据
     * @return 结果
     */
    public boolean checkDictTpyeExist(SysDictData dict) {
        String dictType = dict.getDictType();
        QueryWrapper<SysDictType> queryWrapper = new QueryWrapper<SysDictType>();
        queryWrapper.eq("dict_type", dictType);
        return dictTypeMapper.selectCount(queryWrapper) > 0 ? true : false;
    }
}
